{{>header}}

import { HttpClient, HttpHeaders } from '@angular/common/http';
import type { HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { forkJoin, of, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import type { Observable } from 'rxjs';

import { ApiError } from './ApiError';
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import type { OpenAPIConfig } from './OpenAPI';

{{>functions/isDefined}}


{{>functions/isString}}


{{>functions/isStringWithValue}}


{{>functions/isBlob}}


{{>functions/isFormData}}


{{>functions/base64}}


{{>functions/getQueryString}}


{{>functions/getUrl}}


{{>functions/getFormData}}


{{>functions/resolve}}


{{>angular/getHeaders}}


{{>angular/getRequestBody}}


{{>angular/sendRequest}}


{{>angular/getResponseHeader}}


{{>angular/getResponseBody}}


{{>functions/catchErrorCodes}}


/**
 * Request method
 * @param config The OpenAPI configuration object
 * @param http The Angular HTTP client
 * @param options The request options from the service
 * @returns Observable<T>
 * @throws ApiError
 */
export const request = <T>(config: OpenAPIConfig, http: HttpClient, options: ApiRequestOptions): Observable<T> => {
	const url = getUrl(config, options);
	const formData = getFormData(options);
	const body = getRequestBody(options);

	return getHeaders(config, options).pipe(
		switchMap(headers => {
			return sendRequest<T>(config, options, http, url, formData, body, headers);
		}),
		map(response => {
			const responseBody = getResponseBody(response);
			const responseHeader = getResponseHeader(response, options.responseHeader);
			return {
				url,
				ok: response.ok,
				status: response.status,
				statusText: response.statusText,
				body: responseHeader ?? responseBody,
			} as ApiResult;
		}),
		catchError((error: HttpErrorResponse) => {
			if (!error.status) {
				return throwError(error);
			}
			return of({
				url,
				ok: error.ok,
				status: error.status,
				statusText: error.statusText,
				body: error.error ?? error.statusText,
			} as ApiResult);
		}),
		map(result => {
			catchErrorCodes(options, result);
			return result.body as T;
		}),
		catchError((error: ApiError) => {
			return throwError(error);
		}),
	);
};
